package com.gofaraway.common.exception;

import org.apache.commons.lang3.StringUtils;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;

/**
 * @author ChenPeng
 * @Date 2024/5/17 9:23
 */
public class Error implements Serializable {
    protected static final Map<String, Error> INSTANCE_CACHE = new ConcurrentHashMap();
    private static final Pattern ERROR_CODE_PATTERN = Pattern.compile("(\\d{7})|([a-z]{4}-\\d{5}$)");
    public static final Error SYSTEM_ERROR = new Error("0000001", "系统内部未知错误。");
    public static final Error SYSTEM_ERROR_DEPENDENT_SERVICE_ERROR = new Error("0000002", "系统依赖的外部服务错误。");
    public static final Error SYSTEM_ERROR_DEPENDENT_SERVICE_TIMEOUT = new Error("0000003", "系统依赖的外部服务超时。");
    public static final Error COMMON_ERROR_LOGIN_REQUIRED = new Error("0000004", "用户未登录。");
    public static final Error COMMON_ERROR_PERMISSION_DENIED = new Error("0000005", "用户权限不足，需要的权限为{rights}。");
    public static final Error COMMON_ERROR_PARAMS_IS_NULL = new Error("0000006", "'{param}'不能为空");
    public static final Error COMMON_ERROR_PARAMS_IS_ILLEGAL = new Error("0000007", "参数'{param}'不合法，请重新输入。");
    /** @deprecated */
    public static final Error COMMON_ERROR_LEGACY = new Error("0000000", "{msg}");
    public static final Error COMMON_ERROR_URL_PREFIX_NOT_VALID = new Error("0000008", "URL前缀不合法，需要以http或者https开头。");
    public static final Error COMMON_ERROR_URL_NOT_IN_WHITELIST = new Error("0000009", "URL（{url}）不在受信白名单中，拒绝显示和跳转。");
    public static final Error COMMON_ERROR_MD5_PARAM_IS_NULL = new Error("0000010", "MD5加密参数不能为空");
    private String code;
    private String message;
    private Object data;

    public Error() {
    }

    protected Error(String code, String message) {
        if (INSTANCE_CACHE.containsKey(code)) {
            throw new IllegalArgumentException("相同的错误码已经存在。[error=" + INSTANCE_CACHE.get(code) + "][curMessage=" + message + "]");
        } else {
            this.code = code;
            this.message = message;
            INSTANCE_CACHE.put(code, this);
        }
    }

    protected Error(String code, String message, Object data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public static Error fromCode(String code) {
        return (Error)INSTANCE_CACHE.get(code);
    }

    public Error withData(Object data) {
        return new Error(this.code, this.message, data);
    }

    public Error withMessage(Map<String, String> params) {
        String[] keys = new String[params.size()];
        String[] values = new String[params.size()];
        int i = 0;

        for(Iterator var5 = params.entrySet().iterator(); var5.hasNext(); ++i) {
            Map.Entry<String, String> entry = (Map.Entry)var5.next();
            keys[i] = "{" + (String)entry.getKey() + "}";
            values[i] = (String)entry.getValue();
        }

        String finalMsg = StringUtils.replaceEach(this.message, keys, values);
        return new Error(this.code, finalMsg, this.data);
    }

    public Error withMessage(String msg) {
        return new Error(this.code, msg, this.data);
    }

    public String getCode() {
        return this.code;
    }

    public String getMessage() {
        return this.message;
    }

    public Object getData() {
        return this.data;
    }

    public boolean equals(Object o) {
        if (this == o) {
            return true;
        } else if (o != null && this.getClass() == o.getClass()) {
            Error error = (Error)o;
            return this.code != null ? this.code.equals(error.code) : error.code == null;
        } else {
            return false;
        }
    }

    public int hashCode() {
        return this.code != null ? this.code.hashCode() : 0;
    }

    public String toString() {
        return "Error{code='" + this.code + '\'' + ", message='" + this.message + '\'' + ", data=" + this.data + '}';
    }

    public STORuntimeException newException() {
        return new STORuntimeException(this);
    }

    public void throwException() {
        throw new STORuntimeException(this);
    }

    public STORuntimeException newException(String devDesc) {
        return new STORuntimeException(this, new RuntimeException(devDesc));
    }

    public void throwException(String devDesc) {
        throw new STORuntimeException(this, new RuntimeException(devDesc));
    }

    public STORuntimeException newException(String devDesc, Throwable cause) {
        return new STORuntimeException(this, new RuntimeException(devDesc, cause));
    }

    public void throwException(String devDesc, Throwable cause) {
        throw new STORuntimeException(this, new RuntimeException(devDesc, cause));
    }

    public void throwException(Class<? extends STORuntimeException> eClass) {
        STORuntimeException exception = null;

        try {
            exception = (STORuntimeException)eClass.getConstructor(Error.class).newInstance(this);
        } catch (Exception var4) {
            throw new STORuntimeException(SYSTEM_ERROR, new RuntimeException("动态创建异常类时发生异常。[eClass=" + eClass + "]", var4));
        }

        throw exception;
    }

    public void throwException(Class<? extends STORuntimeException> eClass, String devDesc) {
        STORuntimeException exception = null;

        try {
            exception = (STORuntimeException)eClass.getConstructor(Error.class, Throwable.class).newInstance(this, new RuntimeException(devDesc));
        } catch (Exception var5) {
            throw new STORuntimeException(SYSTEM_ERROR, new RuntimeException("动态创建异常类时发生异常。[eClass=" + eClass + "]", var5));
        }

        throw exception;
    }

    public void throwException(Class<? extends STORuntimeException> eClass, Throwable cause) {
        STORuntimeException exception = null;

        try {
            exception = (STORuntimeException)eClass.getConstructor(Error.class, Throwable.class).newInstance(this, cause);
        } catch (Exception var5) {
            throw new STORuntimeException(SYSTEM_ERROR, new RuntimeException("动态创建异常类时发生异常。[eClass=" + eClass + "]", var5));
        }

        throw exception;
    }

    public static class Params extends HashMap<String, String> {
        public Params() {
        }

        public Params withParam(String key, String value) {
            this.put(key, value);
            return this;
        }
    }
}
